package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.mapper.PermissionMapper;
import cn.com.dcsgo.model.acl.Permission;
import cn.com.dcsgo.model.acl.RolePermission;
import cn.com.dcsgo.service.PermissionService;
import cn.com.dcsgo.service.RolePermissionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * PermissionServiceImpl
 *
 * @author Dcsgo
 * @since 2025/3/24 21:11
 */
@Service
@RequiredArgsConstructor
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
    private final RolePermissionService rolePermissionService;

    /**
     * 获取权限列表-层级结构
     * pid为0的权限是顶层权限
     * 从顶层权限开始递归获取子权限
     * 顶层权限的level为0
     *
     * @return List->Permission
     */
    @Override
    public List<Permission> allPermissionOfHierarchicalStruct() {
        //获取顶层权限
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getParentId, 0);
        List<Permission> topPermissions = baseMapper.selectList(wrapper);
        //设置顶层权限的子权限，及其层级
        topPermissions.forEach(this::setChildrenHelper);
        return topPermissions;
    }

    /**
     * 递归获取所有子权限
     *
     * @param id  父权限id
     * @param ids 所有查找到的子权限集合
     */
    private void getAllChild(Long id, List<Long> ids) {
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getParentId, id);
        baseMapper.selectList(wrapper).forEach(permission -> {
            ids.add(permission.getId());
            getAllChild(permission.getId(), ids);
        });
    }

    @Override
    public void removeContainChild(Long id) {
        // 删除当前权限
        baseMapper.deleteById(id);
        // 获取当前权限的所有子权限
        List<Long> childIds = new ArrayList<>();
        getAllChild(id, childIds);
        //删除所有子权限
        if (!childIds.isEmpty()) {
            baseMapper.deleteBatchIds(childIds);
        }
    }

    @Override
    public List<Permission> getPermissionListByRoleId(Long roleId) {
        //获取所有权限-树状结构
        List<Permission> permissions = allPermissionOfHierarchicalStruct();
        //查询角色已经分配的权限
        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleId, roleId);
        List<Long> assignPermissionIds = rolePermissionService.list(wrapper).stream().map(RolePermission::getPermissionId).collect(Collectors.toList());
        //给所有权限设置是否选中
        Queue<Permission> queue = new LinkedList<>(permissions);
        while (!queue.isEmpty()) {
            Permission cur = queue.remove();
            if (assignPermissionIds.contains(cur.getId())) {
                cur.setSelect(true);
            }
            if (!cur.getChildren().isEmpty()) {
                queue.addAll(cur.getChildren());
            }
        }
        return permissions;
    }

    @Override
    public void assignPermission(Long roleId, Long[] permissionIds) {
        //删除当前角色的所有权限
        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleId, roleId);
        if (!rolePermissionService.list(wrapper).isEmpty()) {
            rolePermissionService.remove(wrapper);
        }
        //添加新的权限
        List<RolePermission> rolePermissionList = new ArrayList<>(permissionIds.length);
        for (Long permissionId : permissionIds) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setPermissionId(permissionId);
            rolePermission.setRoleId(roleId);
            rolePermissionList.add(rolePermission);
        }
        rolePermissionService.saveBatch(rolePermissionList);
    }

    /**
     * 广度优先遍历
     *
     * @param permission permission
     */
    private void setChildrenHelper(Permission permission) {
        Queue<Permission> queue = new LinkedList<>();
        queue.add(permission);
        int level = 0;
        while (!queue.isEmpty()) {
            // 每进入一次循环表示当前层已经遍历完成 层数+1
            level++;
            Permission cur = queue.remove();
            cur.setLevel(level);
            // 获取当前权限的所有子权限
            LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Permission::getParentId, cur.getId());
            List<Permission> children = baseMapper.selectList(wrapper);
            cur.setChildren(children);
            // 将子权限加入队列
            if (!children.isEmpty()) {
                queue.addAll(children);
            }
        }
    }
}
